# Copyright 2021, The Regents of the University of California.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#    1. Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#
#    2. Redistributions in binary form must reproduce the above copyright notice,
#       this list of conditions and the following disclaimer in the documentation
#       and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of The Regents of the University of California.

TOPLEVEL_LANG = verilog

SIM ?= icarus
WAVES ?= 0

COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

DUT      = mqnic_core_pcie_us
TOPLEVEL = $(DUT)
MODULE   = test_$(DUT)
VERILOG_SOURCES += ../../rtl/common/$(DUT).v
VERILOG_SOURCES += ../../rtl/common/mqnic_core_pcie.v
VERILOG_SOURCES += ../../rtl/common/mqnic_core.v
VERILOG_SOURCES += ../../rtl/common/mqnic_interface.v
VERILOG_SOURCES += ../../rtl/common/mqnic_interface_tx.v
VERILOG_SOURCES += ../../rtl/common/mqnic_interface_rx.v
VERILOG_SOURCES += ../../rtl/common/mqnic_port.v
VERILOG_SOURCES += ../../rtl/common/mqnic_port_tx.v
VERILOG_SOURCES += ../../rtl/common/mqnic_port_rx.v
VERILOG_SOURCES += ../../rtl/common/mqnic_egress.v
VERILOG_SOURCES += ../../rtl/common/mqnic_ingress.v
VERILOG_SOURCES += ../../rtl/common/mqnic_l2_egress.v
VERILOG_SOURCES += ../../rtl/common/mqnic_l2_ingress.v
VERILOG_SOURCES += ../../rtl/common/mqnic_rx_queue_map.v
VERILOG_SOURCES += ../../rtl/common/mqnic_ptp.v
VERILOG_SOURCES += ../../rtl/common/mqnic_ptp_clock.v
VERILOG_SOURCES += ../../rtl/common/mqnic_ptp_perout.v
VERILOG_SOURCES += ../../rtl/common/cpl_write.v
VERILOG_SOURCES += ../../rtl/common/cpl_op_mux.v
VERILOG_SOURCES += ../../rtl/common/desc_fetch.v
VERILOG_SOURCES += ../../rtl/common/desc_op_mux.v
VERILOG_SOURCES += ../../rtl/common/event_mux.v
VERILOG_SOURCES += ../../rtl/common/queue_manager.v
VERILOG_SOURCES += ../../rtl/common/cpl_queue_manager.v
VERILOG_SOURCES += ../../rtl/common/tx_fifo.v
VERILOG_SOURCES += ../../rtl/common/rx_fifo.v
VERILOG_SOURCES += ../../rtl/common/tx_req_mux.v
VERILOG_SOURCES += ../../rtl/common/tx_engine.v
VERILOG_SOURCES += ../../rtl/common/rx_engine.v
VERILOG_SOURCES += ../../rtl/common/tx_checksum.v
VERILOG_SOURCES += ../../rtl/common/rx_hash.v
VERILOG_SOURCES += ../../rtl/common/rx_checksum.v
VERILOG_SOURCES += ../../rtl/common/stats_counter.v
VERILOG_SOURCES += ../../rtl/common/stats_collect.v
VERILOG_SOURCES += ../../rtl/common/stats_pcie_if.v
VERILOG_SOURCES += ../../rtl/common/stats_pcie_tlp.v
VERILOG_SOURCES += ../../rtl/common/stats_dma_if_pcie.v
VERILOG_SOURCES += ../../rtl/common/stats_dma_latency.v
VERILOG_SOURCES += ../../rtl/common/mqnic_tx_scheduler_block_rr.v
VERILOG_SOURCES += ../../rtl/common/tx_scheduler_rr.v
VERILOG_SOURCES += ../../rtl/mqnic_app_block_dma_bench.v
VERILOG_SOURCES += ../../lib/eth/rtl/ptp_clock.v
VERILOG_SOURCES += ../../lib/eth/rtl/ptp_clock_cdc.v
VERILOG_SOURCES += ../../lib/eth/rtl/ptp_perout.v
VERILOG_SOURCES += ../../lib/eth/rtl/ptp_ts_extract.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_crossbar.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_crossbar_addr.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_crossbar_rd.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_crossbar_wr.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_ram.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_reg_if.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_reg_if_rd.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_reg_if_wr.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_register_rd.v
VERILOG_SOURCES += ../../lib/axi/rtl/axil_register_wr.v
VERILOG_SOURCES += ../../lib/axi/rtl/arbiter.v
VERILOG_SOURCES += ../../lib/axi/rtl/priority_encoder.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_arb_mux.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_demux.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_fifo.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_fifo_adapter.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_pipeline_fifo.v
VERILOG_SOURCES += ../../lib/axis/rtl/axis_register.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_fifo.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_fifo_raw.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_msix.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_mux.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_mux_rd.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_mux_wr.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_desc_mux.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_ram_demux_rd.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_ram_demux_wr.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_client_axis_sink.v
VERILOG_SOURCES += ../../lib/pcie/rtl/dma_client_axis_source.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v

# module parameters

# Structural configuration
export PARAM_IF_COUNT ?= 1
export PARAM_PORTS_PER_IF ?= 1
export PARAM_SCHED_PER_IF ?= $(PARAM_PORTS_PER_IF)

# PTP configuration
export PARAM_PTP_CLK_PERIOD_NS_NUM = 32
export PARAM_PTP_CLK_PERIOD_NS_DENOM = 5
export PARAM_PTP_CLOCK_PIPELINE ?= 0
export PARAM_PTP_CLOCK_CDC_PIPELINE ?= 0
export PARAM_PTP_USE_SAMPLE_CLOCK ?= 1
export PARAM_PTP_SEPARATE_TX_CLOCK ?= 0
export PARAM_PTP_SEPARATE_RX_CLOCK ?= 0
export PARAM_PTP_PORT_CDC_PIPELINE ?= 0
export PARAM_PTP_PEROUT_ENABLE ?= 0
export PARAM_PTP_PEROUT_COUNT ?= 1

# Queue manager configuration
export PARAM_EVENT_QUEUE_OP_TABLE_SIZE ?= 32
export PARAM_TX_QUEUE_OP_TABLE_SIZE ?= 32
export PARAM_RX_QUEUE_OP_TABLE_SIZE ?= 32
export PARAM_TX_CPL_QUEUE_OP_TABLE_SIZE ?= $(PARAM_TX_QUEUE_OP_TABLE_SIZE)
export PARAM_RX_CPL_QUEUE_OP_TABLE_SIZE ?= $(PARAM_RX_QUEUE_OP_TABLE_SIZE)
export PARAM_EVENT_QUEUE_INDEX_WIDTH ?= 6
export PARAM_TX_QUEUE_INDEX_WIDTH ?= 13
export PARAM_RX_QUEUE_INDEX_WIDTH ?= 8
export PARAM_TX_CPL_QUEUE_INDEX_WIDTH ?= $(PARAM_TX_QUEUE_INDEX_WIDTH)
export PARAM_RX_CPL_QUEUE_INDEX_WIDTH ?= $(PARAM_RX_QUEUE_INDEX_WIDTH)
export PARAM_EVENT_QUEUE_PIPELINE ?= 3
export PARAM_TX_QUEUE_PIPELINE ?= $(shell python -c "print(3 + max($(PARAM_TX_QUEUE_INDEX_WIDTH)-12, 0))")
export PARAM_RX_QUEUE_PIPELINE ?= $(shell python -c "print(3 + max($(PARAM_RX_QUEUE_INDEX_WIDTH)-12, 0))")
export PARAM_TX_CPL_QUEUE_PIPELINE ?= $(PARAM_TX_QUEUE_PIPELINE)
export PARAM_RX_CPL_QUEUE_PIPELINE ?= $(PARAM_RX_QUEUE_PIPELINE)

# TX and RX engine configuration
export PARAM_TX_DESC_TABLE_SIZE ?= 32
export PARAM_RX_DESC_TABLE_SIZE ?= 32

# Scheduler configuration
export PARAM_TX_SCHEDULER_OP_TABLE_SIZE ?= $(PARAM_TX_DESC_TABLE_SIZE)
export PARAM_TX_SCHEDULER_PIPELINE ?= $(PARAM_TX_QUEUE_PIPELINE)
export PARAM_TDMA_INDEX_WIDTH ?= 6

# Interface configuration
export PARAM_PTP_TS_ENABLE ?= 1
export PARAM_TX_CPL_ENABLE ?= $(PARAM_PTP_TS_ENABLE)
export PARAM_TX_CPL_FIFO_DEPTH ?= 32
export PARAM_TX_TAG_WIDTH ?= 16
export PARAM_TX_CHECKSUM_ENABLE ?= 1
export PARAM_RX_RSS_ENABLE ?= 1
export PARAM_RX_HASH_ENABLE ?= 1
export PARAM_RX_CHECKSUM_ENABLE ?= 1
export PARAM_TX_FIFO_DEPTH ?= 32768
export PARAM_RX_FIFO_DEPTH ?= 131072
export PARAM_MAX_TX_SIZE ?= 9214
export PARAM_MAX_RX_SIZE ?= 9214
export PARAM_TX_RAM_SIZE ?= 131072
export PARAM_RX_RAM_SIZE ?= 131072

# Application block configuration
export PARAM_APP_ID ?= $(shell echo $$((0x12348001)) )
export PARAM_APP_ENABLE ?= 1
export PARAM_APP_CTRL_ENABLE ?= 0
export PARAM_APP_DMA_ENABLE ?= 1
export PARAM_APP_AXIS_DIRECT_ENABLE ?= 0
export PARAM_APP_AXIS_SYNC_ENABLE ?= 0
export PARAM_APP_AXIS_IF_ENABLE ?= 0
export PARAM_APP_STAT_ENABLE ?= 0

# DMA interface configuration
export PARAM_DMA_IMM_ENABLE ?= 1
export PARAM_DMA_IMM_WIDTH ?= 32
export PARAM_DMA_LEN_WIDTH ?= 16
export PARAM_DMA_TAG_WIDTH ?= 16
export PARAM_RAM_ADDR_WIDTH ?= $(shell python -c "print((max($(PARAM_TX_RAM_SIZE), $(PARAM_RX_RAM_SIZE))-1).bit_length())")
export PARAM_RAM_PIPELINE ?= 2

# PCIe interface configuration
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512
export PARAM_PF_COUNT ?= 1
export PARAM_VF_COUNT ?= 0
export PARAM_PCIE_TAG_COUNT ?= 256
export PARAM_PCIE_DMA_READ_OP_TABLE_SIZE ?= $(PARAM_PCIE_TAG_COUNT)
export PARAM_PCIE_DMA_READ_TX_LIMIT ?= 16
export PARAM_PCIE_DMA_WRITE_OP_TABLE_SIZE ?= 16
export PARAM_PCIE_DMA_WRITE_TX_LIMIT ?= 3

# Interrupt configuration
export PARAM_IRQ_INDEX_WIDTH ?= $(PARAM_EVENT_QUEUE_INDEX_WIDTH)

# AXI lite interface configuration (control)
export PARAM_AXIL_CTRL_DATA_WIDTH ?= 32
export PARAM_AXIL_CTRL_ADDR_WIDTH ?= 24
export PARAM_AXIL_CSR_PASSTHROUGH_ENABLE ?= 0

# AXI lite interface configuration (application control)
export PARAM_AXIL_APP_CTRL_DATA_WIDTH ?= $(PARAM_AXIL_CTRL_DATA_WIDTH)
export PARAM_AXIL_APP_CTRL_ADDR_WIDTH ?= 24

# Ethernet interface configuration
export PARAM_AXIS_ETH_DATA_WIDTH ?= 512
export PARAM_AXIS_ETH_SYNC_DATA_WIDTH ?= $(PARAM_AXIS_ETH_DATA_WIDTH)
export PARAM_AXIS_ETH_RX_USE_READY ?= 0
export PARAM_AXIS_ETH_TX_PIPELINE ?= 0
export PARAM_AXIS_ETH_TX_FIFO_PIPELINE ?= 2
export PARAM_AXIS_ETH_TX_TS_PIPELINE ?= 0
export PARAM_AXIS_ETH_RX_PIPELINE ?= 0
export PARAM_AXIS_ETH_RX_FIFO_PIPELINE ?= 2

# Statistics counter subsystem
export PARAM_STAT_ENABLE ?= 1
export PARAM_STAT_DMA_ENABLE ?= 1
export PARAM_STAT_PCIE_ENABLE ?= 1
export PARAM_STAT_INC_WIDTH ?= 24
export PARAM_STAT_ID_WIDTH ?= 12

ifeq ($(SIM), icarus)
	PLUSARGS += -fst

	COMPILE_ARGS += -P $(TOPLEVEL).IF_COUNT=$(PARAM_IF_COUNT)
	COMPILE_ARGS += -P $(TOPLEVEL).PORTS_PER_IF=$(PARAM_PORTS_PER_IF)
	COMPILE_ARGS += -P $(TOPLEVEL).SCHED_PER_IF=$(PARAM_SCHED_PER_IF)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_CLK_PERIOD_NS_NUM=$(PARAM_PTP_CLK_PERIOD_NS_NUM)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_CLK_PERIOD_NS_DENOM=$(PARAM_PTP_CLK_PERIOD_NS_DENOM)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_CLOCK_PIPELINE=$(PARAM_PTP_CLOCK_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_CLOCK_CDC_PIPELINE=$(PARAM_PTP_CLOCK_CDC_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_USE_SAMPLE_CLOCK=$(PARAM_PTP_USE_SAMPLE_CLOCK)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_SEPARATE_TX_CLOCK=$(PARAM_PTP_SEPARATE_TX_CLOCK)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_SEPARATE_RX_CLOCK=$(PARAM_PTP_SEPARATE_RX_CLOCK)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_PORT_CDC_PIPELINE=$(PARAM_PTP_PORT_CDC_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_PEROUT_ENABLE=$(PARAM_PTP_PEROUT_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_PEROUT_COUNT=$(PARAM_PTP_PEROUT_COUNT)
	COMPILE_ARGS += -P $(TOPLEVEL).EVENT_QUEUE_OP_TABLE_SIZE=$(PARAM_EVENT_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_QUEUE_OP_TABLE_SIZE=$(PARAM_TX_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_QUEUE_OP_TABLE_SIZE=$(PARAM_RX_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_CPL_QUEUE_OP_TABLE_SIZE=$(PARAM_TX_CPL_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_CPL_QUEUE_OP_TABLE_SIZE=$(PARAM_RX_CPL_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).EVENT_QUEUE_INDEX_WIDTH=$(PARAM_EVENT_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_QUEUE_INDEX_WIDTH=$(PARAM_TX_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_QUEUE_INDEX_WIDTH=$(PARAM_RX_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_CPL_QUEUE_INDEX_WIDTH=$(PARAM_TX_CPL_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_CPL_QUEUE_INDEX_WIDTH=$(PARAM_RX_CPL_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).EVENT_QUEUE_PIPELINE=$(PARAM_EVENT_QUEUE_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_QUEUE_PIPELINE=$(PARAM_TX_QUEUE_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_QUEUE_PIPELINE=$(PARAM_RX_QUEUE_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_CPL_QUEUE_PIPELINE=$(PARAM_TX_CPL_QUEUE_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_CPL_QUEUE_PIPELINE=$(PARAM_RX_CPL_QUEUE_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_DESC_TABLE_SIZE=$(PARAM_TX_DESC_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_DESC_TABLE_SIZE=$(PARAM_RX_DESC_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_SCHEDULER_OP_TABLE_SIZE=$(PARAM_TX_SCHEDULER_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_SCHEDULER_PIPELINE=$(PARAM_TX_SCHEDULER_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).TDMA_INDEX_WIDTH=$(PARAM_TDMA_INDEX_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_CPL_ENABLE=$(PARAM_TX_CPL_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_CPL_FIFO_DEPTH=$(PARAM_TX_CPL_FIFO_DEPTH)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_TAG_WIDTH=$(PARAM_TX_TAG_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_CHECKSUM_ENABLE=$(PARAM_TX_CHECKSUM_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_RSS_ENABLE=$(PARAM_RX_RSS_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_HASH_ENABLE=$(PARAM_RX_HASH_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_CHECKSUM_ENABLE=$(PARAM_RX_CHECKSUM_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH)
	COMPILE_ARGS += -P $(TOPLEVEL).MAX_TX_SIZE=$(PARAM_MAX_TX_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).MAX_RX_SIZE=$(PARAM_MAX_RX_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).TX_RAM_SIZE=$(PARAM_TX_RAM_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).RX_RAM_SIZE=$(PARAM_RX_RAM_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_ID=$(PARAM_APP_ID)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_ENABLE=$(PARAM_APP_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_CTRL_ENABLE=$(PARAM_APP_CTRL_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_DMA_ENABLE=$(PARAM_APP_DMA_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_AXIS_DIRECT_ENABLE=$(PARAM_APP_AXIS_DIRECT_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_AXIS_SYNC_ENABLE=$(PARAM_APP_AXIS_SYNC_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_AXIS_IF_ENABLE=$(PARAM_APP_AXIS_IF_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).APP_STAT_ENABLE=$(PARAM_APP_STAT_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).DMA_IMM_ENABLE=$(PARAM_DMA_IMM_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).DMA_IMM_WIDTH=$(PARAM_DMA_IMM_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).DMA_LEN_WIDTH=$(PARAM_DMA_LEN_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).DMA_TAG_WIDTH=$(PARAM_DMA_TAG_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).RAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).RAM_PIPELINE=$(PARAM_RAM_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).PF_COUNT=$(PARAM_PF_COUNT)
	COMPILE_ARGS += -P $(TOPLEVEL).VF_COUNT=$(PARAM_VF_COUNT)
	COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT)
	COMPILE_ARGS += -P $(TOPLEVEL).PCIE_DMA_READ_OP_TABLE_SIZE=$(PARAM_PCIE_DMA_READ_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).PCIE_DMA_READ_TX_LIMIT=$(PARAM_PCIE_DMA_READ_TX_LIMIT)
	COMPILE_ARGS += -P $(TOPLEVEL).PCIE_DMA_WRITE_OP_TABLE_SIZE=$(PARAM_PCIE_DMA_WRITE_OP_TABLE_SIZE)
	COMPILE_ARGS += -P $(TOPLEVEL).PCIE_DMA_WRITE_TX_LIMIT=$(PARAM_PCIE_DMA_WRITE_TX_LIMIT)
	COMPILE_ARGS += -P $(TOPLEVEL).IRQ_INDEX_WIDTH=$(PARAM_IRQ_INDEX_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIL_CTRL_DATA_WIDTH=$(PARAM_AXIL_CTRL_DATA_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIL_CTRL_ADDR_WIDTH=$(PARAM_AXIL_CTRL_ADDR_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIL_CSR_PASSTHROUGH_ENABLE=$(PARAM_AXIL_CSR_PASSTHROUGH_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIL_APP_CTRL_DATA_WIDTH=$(PARAM_AXIL_APP_CTRL_DATA_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIL_APP_CTRL_ADDR_WIDTH=$(PARAM_AXIL_APP_CTRL_ADDR_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_DATA_WIDTH=$(PARAM_AXIS_ETH_DATA_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_SYNC_DATA_WIDTH=$(PARAM_AXIS_ETH_SYNC_DATA_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_RX_USE_READY=$(PARAM_AXIS_ETH_RX_USE_READY)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_TX_PIPELINE=$(PARAM_AXIS_ETH_TX_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_TX_FIFO_PIPELINE=$(PARAM_AXIS_ETH_TX_FIFO_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_TX_TS_PIPELINE=$(PARAM_AXIS_ETH_TX_TS_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_RX_PIPELINE=$(PARAM_AXIS_ETH_RX_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).AXIS_ETH_RX_FIFO_PIPELINE=$(PARAM_AXIS_ETH_RX_FIFO_PIPELINE)
	COMPILE_ARGS += -P $(TOPLEVEL).STAT_ENABLE=$(PARAM_STAT_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).STAT_DMA_ENABLE=$(PARAM_STAT_DMA_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).STAT_PCIE_ENABLE=$(PARAM_STAT_PCIE_ENABLE)
	COMPILE_ARGS += -P $(TOPLEVEL).STAT_INC_WIDTH=$(PARAM_STAT_INC_WIDTH)
	COMPILE_ARGS += -P $(TOPLEVEL).STAT_ID_WIDTH=$(PARAM_STAT_ID_WIDTH)

	ifeq ($(WAVES), 1)
		VERILOG_SOURCES += iverilog_dump.v
		COMPILE_ARGS += -s iverilog_dump
	endif
else ifeq ($(SIM), verilator)
	COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH

	COMPILE_ARGS += -GIF_COUNT=$(PARAM_IF_COUNT)
	COMPILE_ARGS += -GPORTS_PER_IF=$(PARAM_PORTS_PER_IF)
	COMPILE_ARGS += -GSCHED_PER_IF=$(PARAM_SCHED_PER_IF)
	COMPILE_ARGS += -GPTP_CLK_PERIOD_NS_NUM=$(PARAM_PTP_CLK_PERIOD_NS_NUM)
	COMPILE_ARGS += -GPTP_CLK_PERIOD_NS_DENOM=$(PARAM_PTP_CLK_PERIOD_NS_DENOM)
	COMPILE_ARGS += -GPTP_CLOCK_PIPELINE=$(PARAM_PTP_CLOCK_PIPELINE)
	COMPILE_ARGS += -GPTP_CLOCK_CDC_PIPELINE=$(PARAM_PTP_CLOCK_CDC_PIPELINE)
	COMPILE_ARGS += -GPTP_USE_SAMPLE_CLOCK=$(PARAM_PTP_USE_SAMPLE_CLOCK)
	COMPILE_ARGS += -GPTP_SEPARATE_TX_CLOCK=$(PARAM_PTP_SEPARATE_TX_CLOCK)
	COMPILE_ARGS += -GPTP_SEPARATE_RX_CLOCK=$(PARAM_PTP_SEPARATE_RX_CLOCK)
	COMPILE_ARGS += -GPTP_PORT_CDC_PIPELINE=$(PARAM_PTP_PORT_CDC_PIPELINE)
	COMPILE_ARGS += -GPTP_PEROUT_ENABLE=$(PARAM_PTP_PEROUT_ENABLE)
	COMPILE_ARGS += -GPTP_PEROUT_COUNT=$(PARAM_PTP_PEROUT_COUNT)
	COMPILE_ARGS += -GEVENT_QUEUE_OP_TABLE_SIZE=$(PARAM_EVENT_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -GTX_QUEUE_OP_TABLE_SIZE=$(PARAM_TX_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -GRX_QUEUE_OP_TABLE_SIZE=$(PARAM_RX_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -GTX_CPL_QUEUE_OP_TABLE_SIZE=$(PARAM_TX_CPL_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -GRX_CPL_QUEUE_OP_TABLE_SIZE=$(PARAM_RX_CPL_QUEUE_OP_TABLE_SIZE)
	COMPILE_ARGS += -GEVENT_QUEUE_INDEX_WIDTH=$(PARAM_EVENT_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -GTX_QUEUE_INDEX_WIDTH=$(PARAM_TX_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -GRX_QUEUE_INDEX_WIDTH=$(PARAM_RX_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -GTX_CPL_QUEUE_INDEX_WIDTH=$(PARAM_TX_CPL_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -GRX_CPL_QUEUE_INDEX_WIDTH=$(PARAM_RX_CPL_QUEUE_INDEX_WIDTH)
	COMPILE_ARGS += -GEVENT_QUEUE_PIPELINE=$(PARAM_EVENT_QUEUE_PIPELINE)
	COMPILE_ARGS += -GTX_QUEUE_PIPELINE=$(PARAM_TX_QUEUE_PIPELINE)
	COMPILE_ARGS += -GRX_QUEUE_PIPELINE=$(PARAM_RX_QUEUE_PIPELINE)
	COMPILE_ARGS += -GTX_CPL_QUEUE_PIPELINE=$(PARAM_TX_CPL_QUEUE_PIPELINE)
	COMPILE_ARGS += -GRX_CPL_QUEUE_PIPELINE=$(PARAM_RX_CPL_QUEUE_PIPELINE)
	COMPILE_ARGS += -GTX_DESC_TABLE_SIZE=$(PARAM_TX_DESC_TABLE_SIZE)
	COMPILE_ARGS += -GRX_DESC_TABLE_SIZE=$(PARAM_RX_DESC_TABLE_SIZE)
	COMPILE_ARGS += -GTX_SCHEDULER_OP_TABLE_SIZE=$(PARAM_TX_SCHEDULER_OP_TABLE_SIZE)
	COMPILE_ARGS += -GTX_SCHEDULER_PIPELINE=$(PARAM_TX_SCHEDULER_PIPELINE)
	COMPILE_ARGS += -GTDMA_INDEX_WIDTH=$(PARAM_TDMA_INDEX_WIDTH)
	COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE)
	COMPILE_ARGS += -GTX_CPL_ENABLE=$(PARAM_TX_CPL_ENABLE)
	COMPILE_ARGS += -GTX_CPL_FIFO_DEPTH=$(PARAM_TX_CPL_FIFO_DEPTH)
	COMPILE_ARGS += -GTX_TAG_WIDTH=$(PARAM_TX_TAG_WIDTH)
	COMPILE_ARGS += -GTX_CHECKSUM_ENABLE=$(PARAM_TX_CHECKSUM_ENABLE)
	COMPILE_ARGS += -GRX_RSS_ENABLE=$(PARAM_RX_RSS_ENABLE)
	COMPILE_ARGS += -GRX_HASH_ENABLE=$(PARAM_RX_HASH_ENABLE)
	COMPILE_ARGS += -GRX_CHECKSUM_ENABLE=$(PARAM_RX_CHECKSUM_ENABLE)
	COMPILE_ARGS += -GTX_FIFO_DEPTH=$(PARAM_TX_FIFO_DEPTH)
	COMPILE_ARGS += -GRX_FIFO_DEPTH=$(PARAM_RX_FIFO_DEPTH)
	COMPILE_ARGS += -GMAX_TX_SIZE=$(PARAM_MAX_TX_SIZE)
	COMPILE_ARGS += -GMAX_RX_SIZE=$(PARAM_MAX_RX_SIZE)
	COMPILE_ARGS += -GTX_RAM_SIZE=$(PARAM_TX_RAM_SIZE)
	COMPILE_ARGS += -GRX_RAM_SIZE=$(PARAM_RX_RAM_SIZE)
	COMPILE_ARGS += -GAPP_ID=$(PARAM_APP_ID)
	COMPILE_ARGS += -GAPP_ENABLE=$(PARAM_APP_ENABLE)
	COMPILE_ARGS += -GAPP_CTRL_ENABLE=$(PARAM_APP_CTRL_ENABLE)
	COMPILE_ARGS += -GAPP_DMA_ENABLE=$(PARAM_APP_DMA_ENABLE)
	COMPILE_ARGS += -GAPP_AXIS_DIRECT_ENABLE=$(PARAM_APP_AXIS_DIRECT_ENABLE)
	COMPILE_ARGS += -GAPP_AXIS_SYNC_ENABLE=$(PARAM_APP_AXIS_SYNC_ENABLE)
	COMPILE_ARGS += -GAPP_AXIS_IF_ENABLE=$(PARAM_APP_AXIS_IF_ENABLE)
	COMPILE_ARGS += -GAPP_STAT_ENABLE=$(PARAM_APP_STAT_ENABLE)
	COMPILE_ARGS += -GDMA_IMM_ENABLE=$(PARAM_DMA_IMM_ENABLE)
	COMPILE_ARGS += -GDMA_IMM_WIDTH=$(PARAM_DMA_IMM_WIDTH)
	COMPILE_ARGS += -GDMA_LEN_WIDTH=$(PARAM_DMA_LEN_WIDTH)
	COMPILE_ARGS += -GDMA_TAG_WIDTH=$(PARAM_DMA_TAG_WIDTH)
	COMPILE_ARGS += -GRAM_ADDR_WIDTH=$(PARAM_RAM_ADDR_WIDTH)
	COMPILE_ARGS += -GRAM_PIPELINE=$(PARAM_RAM_PIPELINE)
	COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
	COMPILE_ARGS += -GPF_COUNT=$(PARAM_PF_COUNT)
	COMPILE_ARGS += -GVF_COUNT=$(PARAM_VF_COUNT)
	COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT)
	COMPILE_ARGS += -GPCIE_DMA_READ_OP_TABLE_SIZE=$(PARAM_PCIE_DMA_READ_OP_TABLE_SIZE)
	COMPILE_ARGS += -GPCIE_DMA_READ_TX_LIMIT=$(PARAM_PCIE_DMA_READ_TX_LIMIT)
	COMPILE_ARGS += -GPCIE_DMA_WRITE_OP_TABLE_SIZE=$(PARAM_PCIE_DMA_WRITE_OP_TABLE_SIZE)
	COMPILE_ARGS += -GPCIE_DMA_WRITE_TX_LIMIT=$(PARAM_PCIE_DMA_WRITE_TX_LIMIT)
	COMPILE_ARGS += -GIRQ_INDEX_WIDTH=$(PARAM_IRQ_INDEX_WIDTH)
	COMPILE_ARGS += -GAXIL_CTRL_DATA_WIDTH=$(PARAM_AXIL_CTRL_DATA_WIDTH)
	COMPILE_ARGS += -GAXIL_CTRL_ADDR_WIDTH=$(PARAM_AXIL_CTRL_ADDR_WIDTH)
	COMPILE_ARGS += -GAXIL_CSR_PASSTHROUGH_ENABLE=$(PARAM_AXIL_CSR_PASSTHROUGH_ENABLE)
	COMPILE_ARGS += -GAXIL_APP_CTRL_DATA_WIDTH=$(PARAM_AXIL_APP_CTRL_DATA_WIDTH)
	COMPILE_ARGS += -GAXIL_APP_CTRL_ADDR_WIDTH=$(PARAM_AXIL_APP_CTRL_ADDR_WIDTH)
	COMPILE_ARGS += -GAXIS_ETH_DATA_WIDTH=$(PARAM_AXIS_ETH_DATA_WIDTH)
	COMPILE_ARGS += -GAXIS_ETH_SYNC_DATA_WIDTH=$(PARAM_AXIS_ETH_SYNC_DATA_WIDTH)
	COMPILE_ARGS += -GAXIS_ETH_RX_USE_READY=$(PARAM_AXIS_ETH_RX_USE_READY)
	COMPILE_ARGS += -GAXIS_ETH_TX_PIPELINE=$(PARAM_AXIS_ETH_TX_PIPELINE)
	COMPILE_ARGS += -GAXIS_ETH_TX_FIFO_PIPELINE=$(PARAM_AXIS_ETH_TX_FIFO_PIPELINE)
	COMPILE_ARGS += -GAXIS_ETH_TX_TS_PIPELINE=$(PARAM_AXIS_ETH_TX_TS_PIPELINE)
	COMPILE_ARGS += -GAXIS_ETH_RX_PIPELINE=$(PARAM_AXIS_ETH_RX_PIPELINE)
	COMPILE_ARGS += -GAXIS_ETH_RX_FIFO_PIPELINE=$(PARAM_AXIS_ETH_RX_FIFO_PIPELINE)
	COMPILE_ARGS += -GSTAT_ENABLE=$(PARAM_STAT_ENABLE)
	COMPILE_ARGS += -GSTAT_DMA_ENABLE=$(PARAM_STAT_DMA_ENABLE)
	COMPILE_ARGS += -GSTAT_PCIE_ENABLE=$(PARAM_STAT_PCIE_ENABLE)
	COMPILE_ARGS += -GSTAT_INC_WIDTH=$(PARAM_STAT_INC_WIDTH)
	COMPILE_ARGS += -GSTAT_ID_WIDTH=$(PARAM_STAT_ID_WIDTH)

	ifeq ($(WAVES), 1)
		COMPILE_ARGS += --trace-fst
	endif
endif

include $(shell cocotb-config --makefiles)/Makefile.sim

iverilog_dump.v:
	echo 'module iverilog_dump();' > $@
	echo 'initial begin' >> $@
	echo '    $$dumpfile("$(TOPLEVEL).fst");' >> $@
	echo '    $$dumpvars(0, $(TOPLEVEL));' >> $@
	echo 'end' >> $@
	echo 'endmodule' >> $@

clean::
	@rm -rf iverilog_dump.v
	@rm -rf dump.fst $(TOPLEVEL).fst
